/**
 * 
 */
package uk.co.q3c.deplan.client.domain;

import java.util.Date;

import uk.co.q3c.deplan.client.domain.dag.ChangeInvalidException;
import uk.co.q3c.deplan.client.domain.dag.CycleDetectedException;
import uk.co.q3c.deplan.client.domain.resource.PersistenceReferenceException;
import uk.co.q3c.deplan.client.service.ServiceFactory;
import uk.co.q3c.deplan.server.dao.DomainDao;

import com.googlecode.objectify.Key;

/**
 * Only objects which implement this interface should be saved / queried through the {@link DomainDao}.
 * 
 * @see AbstractDomainObject
 * 
 * @author David Sowerby 27 Oct 2009
 * 
 */
public interface DomainObject {

	boolean getDiscarded();

	/**
	 * As a minimum when an object is discarded, it's <code>discarded</code> field must be set true, and the discarded date set. The
	 * {@link #dereference()} method should also be called so that the target object removes references to itself from other objects
	 * 
	 * @param discarded
	 * @throws CycleDetectedException
	 * @throws ChangeInvalidException
	 * @throws PersistenceReferenceException
	 */
	public void setDiscarded(boolean discarded) throws CycleDetectedException, ChangeInvalidException, PersistenceReferenceException;

	public Date getDiscardedDate();

	public void setDiscardedDate(Date discardedDate);

	/**
	 * Implement to remove references to this object from other objects
	 * 
	 * @throws CycleDetectedException
	 * @throws PersistenceReferenceException
	 */
	void dereference() throws CycleDetectedException, ChangeInvalidException, PersistenceReferenceException;

	public ServiceFactory getConnection();

	void afterLoad(ServiceFactory connection);

	void setConnection(ServiceFactory connection);

	String getCounterGroup();

	DomainKind getKind();

	Long getKeyId();

	void setKeyId(Long keyId);

	void save();

	Key<? extends DomainObject> getKey() throws PersistenceReferenceException;

}
